/////////////////////////////////////////////////////////////////////////////
// Copyright(c) 2012-2015 purang All Rights Reserved
// Name:        rw_lock_win.cc
// Purpose:     
// Author:      syy
// Modified by: 
// Created:     2014/1/3 15:41
// RCS-ID:      
// Licence:     
/////////////////////////////////////////////////////////////////////////////

#include "rw_lock_win.h"

namespace qb
{

	static bool native_rw_locks_supported = false;
	static bool module_load_attempted = false;
	static HMODULE library = NULL;

	typedef void (WINAPI* InitializeSRWLock)(PSRWLOCK);

	typedef void (WINAPI* AcquireSRWLockExclusive)(PSRWLOCK);
	typedef void (WINAPI* ReleaseSRWLockExclusive)(PSRWLOCK);

	typedef void (WINAPI* AcquireSRWLockShared)(PSRWLOCK);
	typedef void (WINAPI* ReleaseSRWLockShared)(PSRWLOCK);

	InitializeSRWLock       initialize_srw_lock;
	AcquireSRWLockExclusive acquire_srw_lock_exclusive;
	AcquireSRWLockShared    acquire_srw_lock_shared;
	ReleaseSRWLockShared    release_srw_lock_shared;
	ReleaseSRWLockExclusive release_srw_lock_exclusive;

	RWLockWin::RWLockWin()
	{
		initialize_srw_lock(&lock_);
	}

	RWLockWin* RWLockWin::Create() 
	{
		if (!LoadModule())
		{
			return NULL;
		}
		return new RWLockWin();
	}

	void RWLockWin::AcquireLockExclusive()
	{
		acquire_srw_lock_exclusive(&lock_);
	}

	void RWLockWin::ReleaseLockExclusive()
	{
		release_srw_lock_exclusive(&lock_);
	}

	void RWLockWin::AcquireLockShared()
	{
		acquire_srw_lock_shared(&lock_);
	}

	void RWLockWin::ReleaseLockShared()
	{
		release_srw_lock_shared(&lock_);
	}

	bool RWLockWin::LoadModule()
	{
		if (module_load_attempted)
		{
			return native_rw_locks_supported;
		}
		module_load_attempted = true;
		// Use native implementation if supported (i.e Vista+)
		library = LoadLibrary(TEXT("Kernel32.dll"));
		if (!library)
		{
			return false;
		}

		initialize_srw_lock =
			(InitializeSRWLock)GetProcAddress(library, "InitializeSRWLock");

		acquire_srw_lock_exclusive =
			(AcquireSRWLockExclusive)GetProcAddress(library,
			"AcquireSRWLockExclusive");
		release_srw_lock_exclusive =
			(ReleaseSRWLockExclusive)GetProcAddress(library,
			"ReleaseSRWLockExclusive");
		acquire_srw_lock_shared =
			(AcquireSRWLockShared)GetProcAddress(library, "AcquireSRWLockShared");
		release_srw_lock_shared =
			(ReleaseSRWLockShared)GetProcAddress(library, "ReleaseSRWLockShared");

		if (initialize_srw_lock && acquire_srw_lock_exclusive &&
			release_srw_lock_exclusive && acquire_srw_lock_shared &&
			release_srw_lock_shared)
		{
			native_rw_locks_supported = true;
		}
		return native_rw_locks_supported;
	}

}  // namespace qb
